﻿using Mozhi.Abp.Core.Offices.Excels;
using Mozhi.Abp.Core.Offices;
using mozhi.smarterp.Finance.Querys;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using mozhi.smarterp.Finance.Accounts;
using System.Linq;
using mozhi.smarterp.Finance.Organizations;

namespace mozhi.smarterp.Finance.Ieps.Export
{
    public class AccountBalanceExportHandler : ExportHandlerBase<AccountBalanceDto>
    {
        private IAccountBalanceAppService _appService;

        private string _moduleName = "科目期初余额";

        private IOrganizationAppService _organizationAppService;

        private IAccountAppService _accountAppService;

        private OrganizationDto _organization;

        private List<AccountDto> _accounts;

        public AccountBalanceExportHandler(IServiceProvider serviceProvider) : base(serviceProvider)
        {
            _appService = serviceProvider.GetService(typeof(IAccountBalanceAppService)) as IAccountBalanceAppService;
            _organizationAppService = serviceProvider.GetService(typeof(IOrganizationAppService)) as IOrganizationAppService;
            _accountAppService = serviceProvider.GetService(typeof(IAccountAppService)) as IAccountAppService;
        }

        protected override async Task<List<AccountBalanceDto>> GetDatasAsync()
        {
            var filter = _query.Filter.IsNullOrEmpty() ? new AccountBalanceQuery() { IncludeDetail = true } :
                JsonConvert.DeserializeObject<AccountBalanceQuery>(_query.Filter);

            filter.IsInitalize = true;
            filter.AllAccount = true;

            var accountBalances = await _appService.FindAsync(filter);

            await LoadOtherInfo();

            return accountBalances;
        }

        protected override async Task<ExcelDocument> GetExcelDocumentAsync()
        {
            var excelDocument = new ExcelDocument();

            excelDocument.FileName = _moduleName;
            excelDocument.FileType = FileType.XLSX;

            excelDocument.Sheets = GetExcelSheets();

            return excelDocument;

        }

        protected override string GetModuleName()
        {
            return _moduleName;
        }

        #region

        private async Task LoadOtherInfo()
        {
            _organization = await _organizationAppService.FindAsync(default);
            _accounts = await _accountAppService.GetListAsync(new AccountQuery() { IncludeDetail = true });
        }

        private List<ExcelSheet> GetExcelSheets()
        {
            var result = new List<ExcelSheet>();

            foreach (var accountBalance in _datas)
            {
                var sheet = result.FirstOrDefault(x => x.SheetName == _moduleName);
                if (sheet == null)
                {
                    sheet = new ExcelSheet();
                    sheet.SheetName = _moduleName;
                    sheet.Columns = GetExcelSheetColumns();
                    sheet.Rows = new List<ExcelSheetRow>();

                    result.Add(sheet);
                }

                var rows = GetExcelSheetRows(accountBalance);

                sheet.Rows.AddRange(rows);

                var dimensionSheet = GetDimensionExcelSheet(accountBalance);
                if (dimensionSheet != null)
                    result.Add(dimensionSheet);
            }
            return result;
        }

        private List<ExcelSheetColumn> GetExcelSheetColumns()
        {
            var columns = new List<ExcelSheetColumn>
            {
                new ExcelSheetColumn()
                {
                    Caption = "编码",
                    Field = "Code",
                    IsRequired = true,
                },
                new ExcelSheetColumn()
                {
                    Caption = "名称",
                    Field = "Name",
                    IsRequired = true,
                },
                new ExcelSheetColumn()
                {
                    Caption = "方向",
                    Field = "Direction",
                },
                new ExcelSheetColumn()
                {
                    Caption = "币别",
                    Field = "CurrencyCode",
                },
                new ExcelSheetColumn()
                {
                    Caption = "期初余额(原币)",
                    Field = "OpeningAmountFr",
                },
                new ExcelSheetColumn()
                {
                    Caption = "期初余额(本位币)",
                    Field = "OpeningAmount",
                },
                new ExcelSheetColumn()
                {
                    Caption = "本年累计借方(原币)",
                    Field = "CurrentYearDebitAmountFr",
                },
                new ExcelSheetColumn()
                {
                    Caption = "本年累计借方(本位币)",
                    Field = "CurrentYearDebitAmount",
                },
                new ExcelSheetColumn()
                {
                    Caption = "本年累计贷方(原币)",
                    Field = "CurrentYearCreditAmountFr",
                },
                 new ExcelSheetColumn()
                {
                    Caption = "本年累计贷方(本位币)",
                    Field = "CurrentYearCreditAmount",
                }
            };

            return columns;
        }

        private ExcelSheet GetDimensionExcelSheet(AccountBalanceDto accountBalance)
        {
            var matchAccount = _accounts.FirstOrDefault(x => x.Id == accountBalance.AccountId);

            if (matchAccount.DimensionItems == null || matchAccount.DimensionItems.Count == 0)
                return null;


            var sheet = new ExcelSheet();

            sheet.SheetName = accountBalance.AccountCode;

            sheet.Columns = GetDimensionExcelSheetColumns(accountBalance.AccountId);

            var balanceItems = accountBalance.Items.Where(x => x.DimensionGroupValueId.HasValue && x.CurrencyId.HasValue);

            sheet.Rows = new List<ExcelSheetRow>();

            foreach (var item in balanceItems)
            {
                var rows = GetDimensionExcelSheetRow(accountBalance, item, matchAccount);

                sheet.Rows.Add(rows);
            }

            return sheet;
        }

        private List<ExcelSheetColumn> GetDimensionExcelSheetColumns(Guid accountId)
        {
            var matchAccount = _accounts.FirstOrDefault(x => x.Id == accountId);

            var columns = new List<ExcelSheetColumn>();

            foreach (var dimensionItem in matchAccount.DimensionItems)
            {
                columns.Add(new ExcelSheetColumn()
                {
                    Caption = dimensionItem.DimensionName,
                    Field = dimensionItem.DimensionId.ToString(),
                });

            };
            columns.AddRange(new List<ExcelSheetColumn>() {
                new ExcelSheetColumn()
                {
                    Caption = "方向",
                    Field = "Direction",
                },
                new ExcelSheetColumn()
                {
                    Caption = "币别",
                    Field = "CurrencyCode",
                },
                new ExcelSheetColumn()
                {
                    Caption = "期初余额(原币)",
                    Field = "OpeningAmountFr",
                },
                new ExcelSheetColumn()
                {
                    Caption = "期初余额(本位币)",
                    Field = "OpeningAmount",
                },
                new ExcelSheetColumn()
                {
                    Caption = "本年累计借方(原币)",
                    Field = "CurrentYearDebitAmountFr",
                },
                new ExcelSheetColumn()
                {
                    Caption = "本年累计借方(本位币)",
                    Field = "CurrentYearDebitAmount",
                },
                new ExcelSheetColumn()
                {
                    Caption = "本年累计贷方(原币)",
                    Field = "CurrentYearCreditAmountFr",
                },
                new ExcelSheetColumn()
                {
                     Caption = "本年累计贷方(本位币)",
                     Field = "CurrentYearCreditAmount",
                }
            });

            return columns;
        }

        private List<ExcelSheetRow> GetExcelSheetRows(AccountBalanceDto accountBalance)
        {
            var result = new List<ExcelSheetRow>();

            var matchAccount = _accounts.FirstOrDefault(x => x.Id == accountBalance.AccountId);

            var balances = accountBalance.Items.Where(x => x.DimensionGroupValueId == null && x.CurrencyId.HasValue).ToList();

            if (balances.Count == 0)
            {
                var row = GetExcelSheetRow(accountBalance, null, matchAccount);
                result.Add(row);
                return result;
            }

            foreach (var balance in balances)
            {
                var row = GetExcelSheetRow(accountBalance, null, matchAccount);
                result.Add(row);
            }

            return result;
        }


        private ExcelSheetRow GetExcelSheetRow(AccountBalanceDto accountBalance, AccountBalanceItemDto balanceItem, AccountDto account)
        {
            var row = new ExcelSheetRow();

            row.Cells =
            [
                new ExcelSheetCell()
                {
                    Value = accountBalance.AccountCode,
                    ValueType = CellValueType.Text
                },
                new ExcelSheetCell()
                {
                    Value = accountBalance.AccountName,
                    ValueType = CellValueType.Text
                },
                new ExcelSheetCell()
                {
                    Value = account==null ? null : account.Direction == Enums.AccountDirectionType.Debit ? "借": "贷",
                    ValueType = CellValueType.Text
                },
                new ExcelSheetCell()
                {
                    Value = _organization.CurrencyCode,
                    ValueType = CellValueType.Text
                },
                new ExcelSheetCell()
                {
                    Value = balanceItem!=null && balanceItem.OpeningAmountFr.HasValue ? balanceItem.OpeningAmountFr.ToString() : "",
                    ValueType = CellValueType.Money
                },
                new ExcelSheetCell()
                {
                    Value = balanceItem != null && balanceItem.OpeningAmountFr.HasValue ? balanceItem.OpeningAmount.ToString() : "",
                    ValueType = CellValueType.Money
                },
                new ExcelSheetCell()
                {
                    Value =balanceItem!=null && balanceItem.CurrentYearDebitAmountFr.HasValue ? balanceItem.CurrentYearDebitAmountFr.ToString() : "",
                    ValueType = CellValueType.Money
                },
                new ExcelSheetCell()
                {
                    Value = balanceItem!=null && balanceItem.CurrentYearDebitAmount.HasValue ? balanceItem.CurrentYearDebitAmount.ToString() : "",
                    ValueType = CellValueType.Money
                },
                new ExcelSheetCell()
                {
                    Value =balanceItem!=null && balanceItem.CurrentYearCreditAmountFr.HasValue ? balanceItem.CurrentYearCreditAmountFr.ToString() : "",
                    ValueType = CellValueType.Money
                },
                new ExcelSheetCell()
                {
                    Value =balanceItem!=null && balanceItem.CurrentYearCreditAmount.HasValue ? balanceItem.CurrentYearCreditAmount.ToString() : "",
                    ValueType = CellValueType.Money
                },
            ];
            return row;
        }

        private ExcelSheetRow GetDimensionExcelSheetRow(AccountBalanceDto accountBalance, AccountBalanceItemDto balanceItem, AccountDto account)
        {
            var row = new ExcelSheetRow();

            row.Cells = new List<ExcelSheetCell>();

            foreach (var dimensionItem in account.DimensionItems)
            {
                var matchDimensionValue = balanceItem.DimensionGroupValueItems.FirstOrDefault(x => x.DataSourceType == dimensionItem.DataSourceType)?.Value;
                var matchDimensionLabel = balanceItem.DimensionGroupValueItems?.FirstOrDefault(x => x.DataSourceType == dimensionItem.DataSourceType)?.Label;

                row.Cells.Add(new ExcelSheetCell()
                {
                    Value = matchDimensionLabel,
                    ValueType = CellValueType.Text
                });
            }

            row.Cells.AddRange(new List<ExcelSheetCell>()
            {

                new ExcelSheetCell()
                {
                    Value = account == null ? null : account.Direction == Enums.AccountDirectionType.Debit ? "借" : "贷",
                    ValueType = CellValueType.Text
                },
                new ExcelSheetCell()
                {
                    Value = _organization.CurrencyCode,
                    ValueType = CellValueType.Text
                },
                new ExcelSheetCell()
                {
                    Value = balanceItem != null && balanceItem.OpeningAmountFr.HasValue ? balanceItem.OpeningAmountFr.ToString() : "",
                    ValueType = CellValueType.Money
                },
                new ExcelSheetCell()
                {
                    Value = balanceItem != null && balanceItem.OpeningAmountFr.HasValue ? balanceItem.OpeningAmount.ToString() : "",
                    ValueType = CellValueType.Money
                },
                new ExcelSheetCell()
                {
                    Value = balanceItem != null && balanceItem.CurrentYearDebitAmountFr.HasValue ? balanceItem.CurrentYearDebitAmountFr.ToString() : "",
                    ValueType = CellValueType.Money
                },
                new ExcelSheetCell()
                {
                    Value = balanceItem != null && balanceItem.CurrentYearDebitAmount.HasValue ? balanceItem.CurrentYearDebitAmount.ToString() : "",
                    ValueType = CellValueType.Money
                },
                new ExcelSheetCell()
                {
                    Value = balanceItem != null && balanceItem.CurrentYearCreditAmountFr.HasValue ? balanceItem.CurrentYearCreditAmountFr.ToString() : "",
                    ValueType = CellValueType.Money
                },
                new ExcelSheetCell()
                {
                    Value = balanceItem != null && balanceItem.CurrentYearCreditAmount.HasValue ? balanceItem.CurrentYearCreditAmount.ToString() : "",
                    ValueType = CellValueType.Money
                }
            });


            return row;
        }

        #endregion
    }
}
